// #pragma once
#include <sys/wait.h>
#include <iostream>
#include <string>
#include <string.h>
#include <cerrno>
#include <unistd.h>
#include <pthread.h>
#include <unordered_map>

#include "Log.hpp"
#include "inetAddr.hpp"
#include "nocopy.hpp"
#include "ThreadPool.hpp"
#include "Task.hpp"
// 网路编程常用套接字

#include <sys/types.h>
#include <sys/socket.h>
#include <functional>
#include <netinet/in.h>
#include <arpa/inet.h>

const int default_backlog = 5;
using task_t = std::function<void()>;
using callback_t = std::function<void(int, InetAddr)>;

class ThreadData
{
public:
    ThreadData(const int &sock, const sockaddr_in &addr) : _sock(sock), _addr(addr) {}
    const int &Sock() const { return _sock; }
    const sockaddr_in &Addr() const { return _addr; }

private:
    int _sock;
    struct sockaddr_in _addr;
};

class TcpServer : public NoCopy
{
private:
    // 获取客户端任务请求
    std::string GetRequest(int sock_fd)
    {
        char request[1024];
        ssize_t n = read(sock_fd, request, sizeof(request) - 1);
        
        if (n > 0)
        {
            request[n] = 0;
        }
        else if (n == 0) // read如果返回值是0，表示读到了文件结尾(对端关闭了连接！)
        {
            lg.LogMessage(Info, "client quit...\n");
            return " ";
        }
        else
        {
            lg.LogMessage(Error, "service read error, errno code: %d, error reason: %s\n", errno, strerror(errno));
            return " ";
        }
        return request;
    }
    // 任务转载
    void Route(int sock_fd, InetAddr addr)
    {
        // 打印任务表
        _func_map["default"](sock_fd, addr);

        std::string request = GetRequest(sock_fd);
        
        lg.LogMessage(Info, "client[%s] request Task: %s\n", addr.PrintAddr().c_str(), request.c_str());
        // 遍历函数表
        for (auto &func : _func_map) // 可能根据特定的函数逻辑要改
        {
            if (request == func.first.c_str())
            {
                // 通过key找到value然后传参调用
                _func_map[request](sock_fd, addr);
                break;
            }
        }
        close(sock_fd);
    }
    // 定义默认任务：打印当前注册的任务和服务器第一次通信
    void DefaultService(int sock_fd, InetAddr addr)
    {
        std::string service_list = " |";
        for (auto &func : _func_map)
        {
            if(func.first == "default") continue;   // default放出去会出bug
            
            service_list += func.first;
            service_list += "|";
        }

        write(sock_fd, service_list.c_str(), service_list.size());
    }

public:
    TcpServer(uint16_t port) : _port(port), _isRunning(false) {}

    // 初始化服务器
    void Init()
    {
        // 创建套接字
        _listen_sock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listen_sock < 0)
        {
            lg.LogMessage(Fatal, "init socket failed, error code: %d, error reason: %s\n", errno, strerror(errno));
            exit(Fatal);
        }
        lg.LogMessage(Info, "init socket success\n");
        
        // 减少绑定错误
        int opt = 1;
        setsockopt(_listen_sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));

        // 定义并配置本地
        struct sockaddr_in local;
        bzero(&local, sizeof(local));

        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY;

        // 绑定本地套接字
        int n = ::bind(_listen_sock, (struct sockaddr *)&local, sizeof(local));
        if (n != 0)
        {
            lg.LogMessage(Fatal, "init bind failed, error code: %d, error reason: %s\n", errno, strerror(errno));
            exit(Fatal);
        }
        lg.LogMessage(Info, "init bind success\n");

        // TCP是面向连接的，需要监听client的链接
        int m = listen(_listen_sock, default_backlog);
        if (m != 0)
        {
            lg.LogMessage(Fatal, "init listen failed, error code: %d, error reason: %s\n", errno, strerror(errno));
        }
        lg.LogMessage(Info, "init listen success, listen_fd: %d\n", _listen_sock);

        // 初始化后创建线程池
        // ThreadPool<Task>::GetInstance->Start();
        zhong::ThreadPool<task_t>::GetInstance()->Start();
    }
    // 启动服务器
    void Start()
    {
        _isRunning = true;
        while (_isRunning == true)
        {
            // 获取连接
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            // accept返回的新的套接字
            int sock_fd = accept(_listen_sock, (struct sockaddr *)&peer, &len); // 用于数据通信
            // accept未接收会阻塞！！

            if (sock_fd < 0)
            {
                lg.LogMessage(Warning, "init accept failed, error code: %d, error reason: %s\n", errno, strerror(errno));
                continue;
            }
            lg.LogMessage(Info, "init acccept success, sock_fd: %d\n", sock_fd);

            // 服务器第一次消息

            InetAddr addr(peer);

            // 接收任务
            // Task t;
            // ThreadPool<Task>::GetInstance()->Push(t);

            // 提前插入default函数
            _func_map.insert(std::make_pair("default", std::bind(&TcpServer::DefaultService, this, sock_fd, addr)));
            // 接收任务
            task_t t = std::bind(&TcpServer::Route, this, sock_fd, addr);
            zhong::ThreadPool<task_t>::GetInstance()->Push(t);
        }
    }
    // 功能注册
    void RegisterFunc(const std::string &func_name, callback_t func)
    {
        _func_map[func_name] = func; // kv绑定
    }

private:
    uint16_t _port; // 服务器端口
    // 用于TCP的链接
    int _listen_sock; // 监听套接字

    bool _isRunning; // 服务器运行状态

    // 构建业务逻辑
    std::unordered_map<std::string, callback_t> _func_map;
};